<template>
	<video :ref="`video${imagesItem.dirPath}`" class="images-item" :style="shs_style" controls muted playsinline
		preload="metadata" :poster="imagesItem.thumbnail">
	</video>
</template>

<script>
	import Hls from 'hls.js';
	import {
		imageNowIP
	} from "@/utils/config"
	import {
		mapGetters
	} from 'vuex';
	export default {
		name: "VideoPlayPage",
		props: {
			imagesItem: {
				type: Object,
				required: true,
				default: () => {}
			},
			shs_style: {
				type: String,
				required: false,
			},
			isDelayFlag: {
				type: Boolean,
				default: true,
				required: false,
			}
		},
		data() {
			return {
				imageNowIP,
				hlsInstance: null, // 保存HLS实例
				video: {}, //视频对象实例
				storageKey: "video", //key存储关键字
				observers: [], // 存储所有的Intersection Observer实例
				initializedVideos: new Set(), // 存储已经初始化的视频元素的引用
			}
		},

		watch: {
			"imagesItem": {
				deep: true, // 深度监听
				immediate: true, // 页面初始化时是否触发回调
				handler: function(value, oldVal) {
					this.$nextTick(() => {
						if (value.uniqueID) {
							this.storageKey = value.dirPath;
							// this.init(value)
							this.checkVisibilityAndInit(value);
						}
					})
				}
			}
		},
		beforeDestroy() {
			// 在组件销毁时断开所有的Intersection Observer
			this.observers.forEach((observer) => {
				observer.disconnect();
			});
		},
		computed: {

		},
		methods: {
			onVisible(videoRef, value, urlPath) {
				console.log(urlPath);
				if (!this.initializedVideos.has(videoRef)) {
					console.log("初始化");
					this.init(value);
					// this.initializedVideos.add(videoRef);
				} else if (videoRef && videoRef.paused) {
					console.log("初始化过");
				}
			},
			onInvisible(video) {
				if (video && !video.paused) {
					video.pause();
				}
			},
			/**添加观察者模式*/
			checkVisibilityAndInit(value) {
				const videoRef = this.$refs[`video${value.dirPath}`];
				if (videoRef) {
					// 创建一个 Intersection Observer 实例来检测可见性
					const observer = new IntersectionObserver((entries) => {
						entries.forEach(entry => {
							if (entry.isIntersecting) {
								this.init(value);
								observer.unobserve(entry.target);
							}
						});
					}, {
						root: null, // 设置为视口
						threshold: 0.5 // 当元素的 50% 可见时触发
					});
					// 开始观察该元素
					observer.observe(videoRef);
					// 存储Observer实例以便后续断开连接
					this.observers.push(observer);

					const observer2 = new IntersectionObserver((entries) => {
						entries.forEach(entry => {
							if (!entry.isIntersecting) {
								this.onInvisible(videoRef);
							}
						});
					}, {
						root: null,
						threshold: 0.5
					});
					// 开始观察该元素
					observer2.observe(videoRef);
					// 存储Observer实例以便后续断开连接
					this.observers.push(observer2);
				}

			},
			/**初始化*/
			init(value) {
				const primaryVideoSrc = value.m3u8path; // 主视频源（HLS）
				const fallbackVideoSrcs = [value.path, `${this.imageNowIP}${value.dirPath}`];
				let video = this.$refs[`video${value.dirPath}`];
				video.addEventListener('loadedmetadata', this.loadedmetadata);
				let currentFallbackIndex = 0; // 当前备用视频源的索引
				if (primaryVideoSrc) {
					// 尝试加载视频源
					this.loadVideoSource(video, primaryVideoSrc, fallbackVideoSrcs, currentFallbackIndex);
				} else {
					this.switchToMp4Fallback(video, fallbackVideoSrcs, currentFallbackIndex);
				}
				video.addEventListener('ended', this.ended);
			},
			/**
			 * 尝试加载视频源
			 * @param {HTMLVideoElement} video 视频元素
			 * @param {string} src 主视频源地址
			 * @param {Array} fallbackSrcs 备用视频源地址数组
			 * @param {number} fallbackIndex 当前尝试的备用视频源索引
			 */
			loadVideoSource(video, src, fallbackSrcs, fallbackIndex) {
				// 尝试加载HLS源（如果需要）
				if (src.endsWith('.m3u8') && Hls.isSupported()) {
					this.loadHlsSource(video, src, () => {
						// HLS加载失败，切换到备用MP4源
						this.switchToMp4Fallback(video, fallbackSrcs, fallbackIndex);
					});
				} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
					video.src = src;
				} else {
					// 直接设置视频源为MP4（或其他格式）
					video.src = src;
					video.addEventListener('error', () => {
						// 视频加载失败，尝试下一个备用源
						this.switchToMp4Fallback(video, fallbackSrcs, fallbackIndex);
					});
				}
			},
			/**
			 * 加载HLS源
			 * @param {HTMLVideoElement} video 视频元素
			 * @param {string} src HLS视频源地址
			 * @param {Function} fallback 加载失败时的回调函数
			 */
			loadHlsSource(video, src, fallback) {
				const hls = new Hls();
				hls.loadSource(src);
				hls.attachMedia(video);
				const handleError = () => {
					if (this.isDelayFlag) {
						setTimeout(() => {
							fallback();
						}, 25000); // 延迟 ? 秒
					} else {
						fallback();
					}
				};
				// video.play()
				hls.on(Hls.Events.ERROR, handleError);
				this.hlsInstance = hls; // 保存HLS实例
			},
			/**
			 * 切换到备用MP4源
			 * @param {HTMLVideoElement} video 视频元素
			 * @param {Array} fallbackSrcs 备用视频源地址数组
			 * @param {number} fallbackIndex 当前尝试的备用视频源索引
			 */
			switchToMp4Fallback(video, fallbackSrcs, fallbackIndex) {
				// 销毁HLS实例（如果存在）
				if (this.hlsInstance) {
					this.hlsInstance.destroy();
					this.hlsInstance = null;
				}
				// 检查是否有更多的备用源可以尝试
				if (fallbackIndex < fallbackSrcs.length) {
					// 尝试下一个备用源
					video.src = fallbackSrcs[fallbackIndex];
					fallbackIndex++; // 增加索引以便下次使用
					video.addEventListener('error', (e) => { // 如果加载失败，继续尝试下一个备用源
						if (fallbackIndex < fallbackSrcs.length) {
							video.src = fallbackSrcs[fallbackIndex];
							fallbackIndex++; // 增加索引以便下次使用
						} else {
							console.error('All video sources failed to load.');
						}
					});
				} else {
					// 没有更多的备用源可以尝试，处理错误情况
					console.error('All video sources failed to load.');
				}
			},

			/** 元数据已加载完毕执行*/
			loadedmetadata() {
				const savedTime = localStorage.getItem(this.storageKey);
				let video = this.$refs[`video${this.storageKey}`];
				if (savedTime && video.currentTime != undefined) {
					video.currentTime = parseFloat(savedTime);
				}
				video.addEventListener('timeupdate', this.timeupdate);
			},
			/**更新缓存 */
			timeupdate() {
				localStorage.setItem(this.storageKey, this.$refs[`video${this.storageKey}`].currentTime);
			},
			/**清空缓存*/
			ended() {
				localStorage.removeItem(this.storageKey);
			},

		}
	}
</script>

<style scoped>
	.images-item {
		width: 100%;
		height: 100%;
		margin: 0;
		padding: 0;
	}
</style>